<!--
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-05-12 10:51:04
 * @Description  : 将主页封装成一个组件
-->
<template>
  <div class="explorer-container flex-1">
    <div class="overflow-auto w-full">
      <n-split
        direction="horizontal"
        style="height: 100vh; width: 100%"
        :max="0.4"
        :min="0"
        :default-size="0.2"
      >
        <template #1>
          <div class="flex">
            <div class="bar w-[10px] h-[100vh]"></div>
            <TreePanels
              :isLinkShare="isLinkShare"
              class="flex-1"
              @node-click="handleBreadClick"
              @menu-select="handleTreeMenuSelect"
            ></TreePanels>
          </div>
        </template>
        <template #2>
          <div class="file-info-container w-full overflow-auto">
            <div class="header">
              <div class="header-nav">
                <n-button-group size="small" class="float-left">
                  <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button
                        class="transform rotate-180"
                        :disabled="!explorerStore.canBack"
                        @click="handleBack"
                      >
                        <SvgIcon icon="qianjin" size="18px"></SvgIcon>
                      </n-button>
                    </template>
                    后退
                  </n-tooltip>

                  <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button
                        :disabled="!explorerStore.canforword"
                        @click="handleForward"
                      >
                        <SvgIcon icon="qianjin" size="18px"></SvgIcon>
                      </n-button>
                    </template>
                    前进
                  </n-tooltip>
                </n-button-group>
                <div class="g-scroll">
                  <div :class="`g-pesudo`"></div>
                  <BreadCrumb
                    :breads="breads"
                    class="g-content"
                    @bread-click="handleBreadClick"
                  ></BreadCrumb>
                </div>
                <n-button-group size="small" class="ml-400px float-left">
                  <!-- <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button>
                        <SvgIcon icon="shoucang" size="18px"></SvgIcon>
                      </n-button>
                    </template>
                    收藏
                  </n-tooltip> -->

                  <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button @click="handleSourceDropSelect('reflesh')">
                        <SvgIcon icon="shuaxin1" size="18px"></SvgIcon>
                      </n-button>
                    </template>
                    刷新
                  </n-tooltip>
                </n-button-group>

                <n-tag
                  v-if="
                    explorerStore.curNav &&
                    explorerStore.curNav.targetType === 2
                  "
                  round
                  class="text-[13px] float-left mx-2 cursor-pointer"
                  @click="dialogs.docAuth = true"
                >
                  <SvgIcon
                    icon="yuandian"
                    :color="sourceRole.label"
                    class="text-[13px] float-left mr-1"
                    size="14px"
                  ></SvgIcon>
                  {{ sourceRole?.name || '无权限' }}
                </n-tag>

                <n-input-group
                  class="float-left ml-1"
                  :style="{ width: '240px' }"
                >
                  <n-input
                    size="small"
                    class="h-[28px]"
                    placeholder=""
                    :maxlength="50"
                    @keyup="handleKeyWordUp"
                    v-model:value="pageInfo.filename"
                  />

                  <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button class="h-[28px] mr-3" @click="loadSources">
                        <SvgIcon icon="sousuo"></SvgIcon>
                      </n-button>
                    </template>
                    搜索，支持文件类型，文件夹路径，模糊匹配
                  </n-tooltip>
                </n-input-group>
              </div>
              <div class="file-actions flex mt-2 justify-between items-center">
                <div class="flex">
                  <source-action
                    :sourceAuths="sourceAuths"
                    :checkRowLength="checkedRowKeys.length"
                    @key-select="handleSourceDropSelect"
                  ></source-action>
                </div>

                <!-- <template ></template> -->
                <!-- 视图模式 -->
                <div class="flex">
                  <n-button-group size="small">
                    <n-tooltip trigger="hover">
                      <template #trigger>
                        <n-button
                          type="tertiary"
                          @click="handleToChangeViewModel('grid')"
                          class="text-[13px]"
                          :class="{
                            'btn-active': explorerStore.viewModel === 'grid'
                          }"
                        >
                          <SvgIcon icon="shitumoshi" size="16px"></SvgIcon>
                        </n-button>
                      </template>
                      图标排列
                    </n-tooltip>

                    <n-tooltip trigger="hover">
                      <template #trigger>
                        <n-button
                          type="tertiary"
                          @click="handleToChangeViewModel('list')"
                          class="text-[13px]"
                          :class="{
                            'btn-active': explorerStore.viewModel === 'list'
                          }"
                        >
                          <SvgIcon
                            icon="shitumoshi-liebiao"
                            size="16px"
                          ></SvgIcon>
                        </n-button>
                      </template>
                      列表排列
                    </n-tooltip>
                  </n-button-group>

                  <n-tooltip trigger="hover">
                    <template #trigger>
                      <n-button
                        type="tertiary"
                        @click="handleToChangeShowDesc"
                        class="text-[13px] ml-2 h-[28px]"
                        :class="{
                          'btn-active': '' + explorerStore.showDesc !== '1'
                        }"
                        :focusable="false"
                      >
                        <SvgIcon icon="zhedie1" size="16px"></SvgIcon>
                      </n-button>
                    </template>
                    属性信息
                  </n-tooltip>
                </div>
              </div>
            </div>

            <NSplit
              direction="horizontal"
              style="height: 100%; width: 100%"
              :max="0.75"
              :min="0.25"
              :size="Number(explorerStore.showDesc)"
              @update:size="handleShowDesc"
            >
              <template #1>
                <div
                  id="my-table"
                  class="myTable"
                  @contextmenu="hanldeOutContextMenu"
                  @keyup="handleKeyUp"
                  @dragover="fileDragover"
                  @drop="fileDrop"
                >
                  <wp-data-table
                    v-if="explorerStore.viewModel === 'list'"
                    v-loading="loading"
                    :data="data"
                    :isSort="false"
                    :draggable="true"
                    :checked-row-keys="checkedRowKeys"
                    :columns="columns"
                    :pageSize="500"
                    :max-height="'calc(100vh - 180px)'"
                    @page-change="handlePageChange"
                    @item-click="handleItemClick"
                    @item-db-click="handleToOpenSource"
                    @select-change="handleSelectChange"
                    :handle-load="handleLoad"
                    :pages="pageResultInfo.pages"
                    :total="pageResultInfo.total"
                    :onlyCheckAll="true"
                    :on-contextmenu="userContextMenuProps"
                    @mouseover="userMouseoverProps"
                    @mouseleave="userMouseleaveProps"
                    @drop="handleDrop"
                    @dragover="handleDragOver"
                  >
                  </wp-data-table>

                  <GridSourceList
                    v-else
                    v-loading="loading"
                    :data="data"
                    :checked-row-keys="checkedRowKeys"
                    :pageSize="500"
                    :max-height="'calc(100vh - 180px)'"
                    @page-change="handlePageChange"
                    @item-click="handleItemClick"
                    @item-db-click="handleToOpenSource"
                    @select-change="handleSelectChange"
                    :pages="pageResultInfo.pages"
                    :total="pageResultInfo.total"
                    :on-contextmenu="userContextMenuProps"
                    @mouseover="userMouseoverProps"
                    @mouseleave="userMouseleaveProps"
                    @create-finish="onEditFinish"
                    @reflesh="afterOpt"
                  ></GridSourceList>
                </div>
              </template>
              <template #2>
                <source-desc class="h-[100%]"></source-desc>
              </template>
            </NSplit>

            <n-dropdown
              placement="bottom-start"
              trigger="manual"
              :x="sourceDropDown.x"
              :y="sourceDropDown.y"
              :options="sourceDropDownOptions"
              :show="sourceDropDown.showDropdown"
              :on-clickoutside="handleSourceDropClickOutside"
              @select="handleSourceDropSelect"
              :render-label="renderSourceDropDownMenu"
            />
          </div>
        </template>
      </n-split>
    </div>

    <MyDialog
      default-width="35%"
      default-height="90%"
      v-if="dialogs.upload"
      @close="dialogs.upload = false"
    >
      <template #title>
        <div class="flex items-center text-[#555]">
          <SvgIcon icon="xiazaijiantou-copy"></SvgIcon>
          多文件上传
        </div>
      </template>
      <upload-panel
        style="padding: 10px; padding-top: 0"
        @close="handleUploadFinish"
      ></upload-panel>
    </MyDialog>

    <!-- 文件属性的面板 -->
    <MyDialog
      default-width="30%"
      default-height="95%"
      v-if="dialogs.sourceDesc"
      @close="dialogs.sourceDesc = false"
    >
      <template #title>
        <div class="flex items-center text-[#555] text-[13px]">
          <SvgIcon icon="jinggao" class="mr-1" color="#13b1fe"></SvgIcon>
          属性
        </div>
      </template>
      <source-desc tab-placement="top" :showCloseIcon="false"></source-desc>
    </MyDialog>

    <!-- 外链分享的dialog -->
    <MyDialog
      default-width="40%"
      default-height="90%"
      v-if="dialogs.linkShare"
      @close="dialogs.linkShare = false"
    >
      <template #title>
        <div class="flex items-center text-[#555] text-[13px]">
          <SvgIcon icon="zhuanfa2-copy" class="mr-1"></SvgIcon>
          外链分享
        </div>
      </template>
      <LinkSharePanel
        :source-id="shareSource.id"
        @close="handleLinkShareFinish"
      ></LinkSharePanel>
    </MyDialog>

    <!-- 内部分享的dialog -->
    <MyDialog
      default-width="40%"
      default-height="90%"
      v-if="dialogs.shareTo"
      @close="dialogs.shareTo = false"
    >
      <template #title>
        <div class="flex items-center text-[#555] text-[13px]">
          <SvgIcon icon="fenxiang-copy" class="mr-1"></SvgIcon>
          协作分享
        </div>
      </template>
      <ShareToPanel
        :source-id="shareSource.id"
        class="p-3"
        @open-doc-auth="dialogs.docAuth = true"
        @close="handleShareToFinish"
      ></ShareToPanel>
    </MyDialog>

    <!-- 文档权限的dialog -->
    <MyDialog
      default-width="42%"
      default-height="90%"
      v-if="dialogs.docAuth"
      @close="dialogs.docAuth = false"
    >
      <template #title>
        <div class="flex items-center text-[#555] text-[13px]">
          内部成员，文档协作级别权限表
        </div>
      </template>
      <DocAuthTable class="p-3"></DocAuthTable>
    </MyDialog>
  </div>

  <!-- 展示文件详细信息的tooltip -->
  <n-popover
    :show="sourcePopover.showPopover"
    :x="sourcePopover.x"
    :y="sourcePopover.y"
    :show-arrow="false"
    trigger="manual"
    :raw="true"
    placement="bottom-start"
    content-class="bg-yellow-100 py-2"
    arrow-wrapper-class="bg-yellow-100 rounded"
    :on-clickoutside="() => (sourcePopover.showPopover = false)"
  >
    <n-grid
      x-gap="12"
      y-gap="6"
      :cols="3"
      class="mx-2 text-[13px]"
      v-if="hoverSource"
    >
      <n-gi :span="1" class="text-[#555] font-bold"> 名称： </n-gi>
      <n-gi :span="2"> {{ hoverSource.filename }} </n-gi>
      <n-gi :span="1" class="text-[#555] font-bold"> 路径： </n-gi>
      <n-gi :span="2">
        <n-breadcrumb class="w-full">
          <n-breadcrumb-item
            v-for="item in hoverSource.pathInfo"
            :key="item.id"
            @click="handleBreadClick"
          >
            <n-ellipsis style="max-width: 200px">
              {{ getLabelName(item.id, item.filename) }}
            </n-ellipsis>
          </n-breadcrumb-item>
        </n-breadcrumb>
      </n-gi>

      <n-gi :span="1" class="text-[#555] font-bold"> 大小：</n-gi>
      <n-gi :span="2"> {{ hoverSource.sizeDesc }} </n-gi>
      <n-gi :span="1" class="text-[#555] font-bold"> 创建时间： </n-gi>
      <n-gi :span="2">
        {{ formatTime(hoverSource.createTime) }}
      </n-gi>
      <n-gi :span="1" class="text-[#555] font-bold"> 修改时间： </n-gi>
      <n-gi :span="2">
        {{ formatTime(hoverSource.updateTime) }}
      </n-gi>

      <n-gi :span="1" class="text-[#555] font-bold"> 创建者： </n-gi>
      <n-gi :span="2">
        <div class="flex items-center">
          <n-avatar
            round
            :size="16"
            :src="renderSourceAvator(hoverSource)"
            class="mr-1"
          />
          <span>{{ renderUserInfo(hoverSource) }}</span>
        </div>
      </n-gi>
      <n-gi :span="1" class="text-[#555] font-bold"> 修改者： </n-gi>
      <n-gi :span="2">
        <div class="flex items-center">
          <n-avatar
            round
            :size="16"
            :src="renderSourceAvator(hoverSource)"
            class="mr-1"
          />
          <span>{{ renderUserInfo(hoverSource) }}</span>
        </div>
      </n-gi>
      <n-gi :span="1" class="text-[#555]" v-if="hoverSource.targetType === 2">
        我的权限：
      </n-gi>
      <n-gi :span="2" v-if="hoverSource.targetType === 2">
        <n-tag round size="small">
          <div class="flex items-center">
            <SvgIcon
              icon="yuandian"
              class="mr-1"
              :color="sourceRole.label"
            ></SvgIcon>
            {{ sourceRole.name || '无权限' }}
          </div>
        </n-tag>
      </n-gi>
      <n-gi :span="1" class="text-[#555] font-bold" v-if="hoverSource.desc">
        描述说明：
      </n-gi>
      <n-gi :span="2" v-if="hoverSource.desc">{{ hoverSource.desc }} </n-gi>
    </n-grid>
  </n-popover>
</template>

<script setup lang="ts">
import { useMessage, useDialog, NEllipsis } from 'naive-ui'
import useUserStore from '@/stores/modules/user'
import useExplorerStore from '@/stores/modules/explorer'
import {
  binSource,
  createSourceDir,
  delSource,
  getSourceByPage,
  renameSource,
  createFile,
  getFileTypeSourceByPage,
  getBinSourceByPage,
  recSource,
  moveSource,
  copySource,
  fileDownload,
  zipDownload
} from '@/api/source'
import type { IndexObj } from '@/types/commom'
import type { SourceRowData } from '@/types/source'
import { navTypeList } from '@/constants/explorer'
import {
  downLoadFile,
  getFileTypeBySuffix,
  getFileTypeInfoByType,
  renderDropLabel,
  renderFileType,
  renderUserAvator,
  renderSourceAvator
} from '@/utils/commonBusiness'
import {
  formatTime,
  arraysIsEqual,
  formatFilenameByInc,
  convertFromBytes
} from '@/utils/index'
import { load } from '@/utils/loading'
import SvgIcon from '@/components/SvgIcon/index.vue'
import DisableUserPic from '@/assets/images/default-avata-disable.jpg'
import TreePanels from './components/TreePanels.vue'
import SourceDesc from './components/SourceDesc.vue'
import SourceAction from './components/SourceAction.vue'
import UploadPanel from './components/UploadPanel.vue'
import {
  DropDownType,
  contextMenus,
  navTypeToRange
} from './constants/dropDown'
import LinkSharePanel from '../Share/components/LinkSharePanel.vue'
import ShareToPanel from '../Share/components/ShareToPanel.vue'
import DocAuthTable from './components/DocAuthTable.vue'
import GridSourceList from './components/GridSourceList.vue'
import {
  cancelShare,
  getUserInnerShareByPage,
  getUserShareByPage
} from '@/api/share'
import { events } from '@/utils/bus'
import { useSourceAuth, useSourceRole } from '@/hooks/useSourceAuth'

const { sourceAuths, loadSourceAuth } = useSourceAuth()
const { sourceRole, loadSourceRole } = useSourceRole()
const router = useRouter()

const message = useMessage()
const dialog = useDialog()

const userStore = useUserStore()
const explorerStore = useExplorerStore()

const props = withDefaults(
  defineProps<{
    needDir?: boolean
    isLinkShare?: boolean
  }>(),
  {
    needDir: false,
    isLinkShare: false
  }
)

// 日志监听
onMounted(() => {
  events.on('node-click', (res: any) => {
    if (res.sourceInfo) {
      handleBreadClick(res.nav, true, res.sourceInfo)
    } else {
      handleBreadClick(res.nav, true)
    }
  })

  events.on('edit-share', (res: any) => {
    if (res.type === 0) {
      handleToLinkSource(res.curSourceDesc)
    } else if (res.type === 1) {
      handleToShareToSource(res.curSourceDesc)
    }
  })
})

onBeforeMount(() => {
  events.off('node-click')
})

// 处理当前用户根文件夹名称显示
const getLabelName = (id: string, label: string) => {
  if (id === userStore.userInfo?.rootSourceId) {
    return '个人空间'
  }
  return label
}

// 面包屑导航(我们希望维护一个自己的数组，自己管理nav)
const breads = computed(() => {
  if (!explorerStore.curNav) {
    return []
  }

  // 处理文件类型nav
  if (explorerStore.curNav.myType === navTypeList.SOURCE) {
    if (explorerStore.curNav.pathInfo) {
      // 渲染pathInfo为面包屑
      return explorerStore.curNav.pathInfo.map((item: any) => {
        const curLabel = getLabelName(item.id, item.filename)
        return {
          key: item.id,
          label: curLabel,
          myIcon: curLabel === '个人空间' ? 'home' : 'wenjianjia2',
          myType: navTypeList.SOURCE
        }
      })
    }

    return [
      {
        key: explorerStore.curNav.key,
        label: getLabelName(
          explorerStore.curNav.key,
          explorerStore.curNav.label
        ),
        myIcon: explorerStore.curNav.myIcon
      }
    ]
  } else {
    // 对于其他类型
    return [
      {
        key: explorerStore.curNav.key,
        label: getLabelName(
          explorerStore.curNav.key,
          explorerStore.curNav.label
        ),
        myIcon: explorerStore.curNav.myIcon
      }
    ]
  }
})

// 面包屑被点击
const handleBreadClick = async (
  item: any,
  needPush = true,
  checkRowId: any = undefined
) => {
  // 就是将nav要进行修改,其实就是进行source资源的加载，同时获取到信息，赋值给nav
  checkedRowKeys.value = []
  // console.log(needPush, '111')

  if (checkRowId) {
    // console.log('has-row-id')
  }
  // 相同则不push
  if (
    explorerStore.curNav &&
    item.key === explorerStore.curNav.key &&
    needPush
  ) {
    if (checkRowId) {
      const res = data.value.find((item) => item.id === checkRowId.id)
      if (res) {
        // console.log('row')
        checkedRowKeys.value = [res]
      }
    }
    return
  }
  if (item.myType === navTypeList.SOURCE || item.myType === navTypeList.DEP) {
    pageInfo.parentId = item.key
    if (item.myType === navTypeList.DEP) {
      // 对于部门，取部门根目录
      pageInfo.parentId =
        item.Sources && item.Sources.length ? item.Sources[0].id : '-2'
    }
    // 在这之前，nav还没有发生跳转，保存之前的nav
    const beforeNav = explorerStore.curNav

    // 先更新一下item，这时候pathInfo可能没有，重新获取一下
    explorerStore.setCurNav({
      ...item
    })
    loadSources()
      .then(() => {
        // console.log('after', item)
        // console.log(needPush)

        if (needPush) {
          explorerStore.pushHistoryNav(
            curFile.value
              ? {
                  ...curFile.value,
                  key: curFile.value!.id,
                  label: curFile.value!.filename,
                  myType: navTypeList.SOURCE
                }
              : {
                  ...item
                }
          )

          // console.log(checkRowId)

          if (checkRowId) {
            // console.log('has-row-id')
            const res = data.value.find((item) => item.id === checkRowId.id)
            if (res) {
              checkedRowKeys.value = [res]
            }
          }
        }
      })
      .catch(() => {
        explorerStore.setCurNav(beforeNav)
      })
  } else {
    // 根据类型的不同去加载，key的不同
    if (needPush) {
      explorerStore.pushHistoryNav({
        ...item,
        key: item.key,
        label: item.label
      })
    }
    loadSources()
  }
}

// 前进
const handleForward = () => {
  explorerStore.nextNavIndex()
  handleBreadClick(explorerStore.curNav, false)
}

// 后退
const handleBack = () => {
  explorerStore.backNavIndex()
  handleBreadClick(explorerStore.curNav, false)
}

// ====================================== 表格数据获取 ========================================
const data = ref<SourceRowData[]>([])
const curFile = ref<SourceRowData>()
const pageInfo = reactive<any>({
  page: 1,
  pageSize: 500,
  parentId: '',
  filename: ''
})

const handleKeyWordUp = (e: KeyboardEvent) => {
  if (e.key === 'Enter') {
    loadSources()
  }
}

const pageResultInfo = reactive({
  pages: 0,
  total: 0
})

const loading = ref(false)

// 定义一个可编辑的表单列组件
const ShowOrEdit = defineComponent({
  props: {
    value: [String, Number],
    onUpdateValue: [Function, Array],
    isEdit: [Boolean],
    onEditChange: [Function, Array],
    onFinish: [Function, Array]
  },
  setup(props: any) {
    watch(
      () => props.isEdit,
      (newValue) => {
        if (newValue) {
          nextTick(() => {
            // console.log(inputRef.value)
            inputRef.value!.focus()
            // inputRef.value.select()
          })
        }
      },
      {
        immediate: true
      }
    )
    // const isEdit = ref(false)
    const inputRef = ref<any>(null)
    const inputValue = ref(props.value)
    const initValue = ref(props.value)
    function handleOnClick(e: MouseEvent) {
      // console.log('click')

      e.stopPropagation()
      props.onEditChange(true)
      if (props.isEdit) {
        nextTick(() => {
          inputRef.value!.focus()
          // inputRef.value.select()
        })
      }
    }
    function handleChange() {
      props.onUpdateValue(inputValue.value)
      props.onEditChange(false)
    }

    function handleBlur() {
      props.onUpdateValue(inputValue.value)
      props.onEditChange(false)
      props.onFinish(initValue.value)
    }
    return () =>
      h(
        'div',
        {
          style: 'min-height: 22px',
          class: 'cursor-text',
          onClick: handleOnClick,
          onmousedown(e: MouseEvent) {
            e.stopPropagation()
            e.preventDefault()
          }
        },
        props.isEdit
          ? h(NInput, {
              ref: inputRef,
              value: inputValue.value as any,
              onUpdateValue: (v: any) => {
                inputValue.value = v
              },
              onChange: handleChange,
              onBlur: handleBlur,
              onKeydown(e: KeyboardEvent) {
                // e.preventDefault()
                // e.stopPropagation()
                if (e.key === 'Enter') {
                  handleChange()
                }
              }
            })
          : h(
              NEllipsis,
              {
                style: {
                  'max-width': '100px'
                },
                tooltip: {
                  raw: true,
                  'content-class': 'bg-yellow-100 text-[#000] p-2',
                  'arrow-class': '!bg-yellow-100'
                }
              },
              { default: () => props.value }
            )
      )
  }
})

const checkedRowKeys = ref<SourceRowData[]>([])

const onEditFinish = (initValue: any, row: SourceRowData) => {
  if (row.createType === 'createDir') {
    handleCreateDir(row)
  } else if (row.createType === 'createFile') {
    handleCreateFile(row)
  } else if (row.createType === 'rename') {
    if (initValue === row.filename) {
      return
    }
    handleRenameSource(row)
  }
}

const columns = computed(() => {
  const baseColumns = [
    {
      type: 'selection',
      minWidth: 30,
      width: 30
    },
    {
      title: '名称',
      key: 'name',
      minWidth: 200,
      width: 200,
      render: (row: IndexObj) => {
        return h(
          'div',
          {
            style: {
              width: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              fontSize: '13px'
            }
          },
          [
            h(
              'div',
              {
                style: {
                  display: 'flex',
                  alignItems: 'center',
                  fontSize: '13px'
                },
                onClick(e: MouseEvent) {
                  e.stopPropagation()
                }
              },
              [
                h(SvgIcon, {
                  icon: row.isDir
                    ? getFileTypeInfoByType(row.type).myIcon
                    : getFileTypeBySuffix(row.filename).myIcon,
                  size: '16px',
                  class: 'mr-2'
                }),

                h(ShowOrEdit, {
                  value: row.filename,
                  isEdit: row.isEdit,
                  onEditChange(v: boolean) {
                    if (row.deleteFlag) {
                      row.isEdit = false
                      return
                    }
                    row.isEdit = v
                  },
                  onUpdateValue(v: any) {
                    row.filename = v
                    // 进行重命名
                  },
                  onFinish(initValue: any) {
                    onEditFinish(initValue, row as any)
                  }
                })
              ]
            ),
            h(
              'div',
              {
                style: {
                  display: 'flex',
                  alignItems: 'center',
                  fontSize: '13px'
                }
              },
              [
                row.Share && row.Share.isShareTo
                  ? h(SvgIcon, {
                      icon: 'fenxiang-copy',
                      size: '16px',
                      class: 'mr-1 cursor-pointer',
                      onClick: () => {
                        handleToShareToSource(row as SourceRowData)
                      }
                    })
                  : '',
                row.Share && row.Share.isLink
                  ? h(SvgIcon, {
                      icon: 'zhuanfa2-copy',
                      size: '16px',
                      class: 'mr-1 cursor-pointer',
                      onClick: () => {
                        handleToLinkSource(row as SourceRowData)
                      }
                    })
                  : ''
              ]
            )
          ]
        )
      }
    },
    {
      ellipsis: {
        tooltip: true
      },
      title: '类型',
      key: 'type',
      minWidth: 120,
      width: 120,
      render: (row: IndexObj) => {
        return renderFileType(row.type)
      }
    },
    {
      title: '大小',
      key: 'type',
      align: 'right',
      minWidth: 120,
      width: 120,
      render: (row: IndexObj) => {
        if (!row.isDir) {
          return row.file ? convertFromBytes(row.file.size) : '0B'
        }
        return `${row.hasFile + row.hasFolder}项 ${
          row.file ? convertFromBytes(row.file.size) : '0B'
        }`
      }
    },
    {
      title: '修改时间',
      key: 'updateTime',
      minWidth: 150,
      width: 150,
      render(row: IndexObj) {
        return formatTime(row.updateTime)
      }
    },
    {
      range: [navTypeList.SHARE_TO_ME],
      title: '分享者',
      key: 'createUser',
      minWidth: 150,
      width: 150,
      render(row: IndexObj) {
        if (!row.user) {
          return renderUserAvator(DisableUserPic, '已删除')
          // return '已删除用户'
        }
        const curUsername =
          userStore.userInfo?.id === row.user.id ? '我自己' : row.user.username
        return renderUserAvator(row.user.avator, curUsername)
      }
    },
    {
      title: '修改者',
      key: 'updateTime',
      minWidth: 150,
      width: 150,
      render(row: IndexObj) {
        if (!row.user) {
          return renderUserAvator(DisableUserPic, '已删除')
        }
        const curUsername =
          userStore.userInfo?.id === row.user.id ? '我自己' : row.user.username
        return renderUserAvator(row.user.avator, curUsername)
      }
    },
    {
      title:
        explorerStore.curNav?.myType === navTypeList.USER_SHARE
          ? '分享时间'
          : '创建时间',
      key: 'createTime',
      range: [navTypeList.SOURCE, navTypeList.USER_SHARE],
      minWidth: 150,
      width: 150,
      render(row: IndexObj) {
        return formatTime(row.createTime)
      }
    },
    {
      range: [navTypeList.USER_SHARE_LINK],
      title: '浏览数',
      key: 'numView',
      minWidth: 60,
      width: 60,
      ellipsis: {
        tooltip: true
      },
      render(row: IndexObj) {
        return row.numView || 0
      }
    },
    {
      range: [navTypeList.USER_SHARE_LINK],
      title: '下载数',
      key: 'numDownload',
      minWidth: 60,
      width: 60,
      ellipsis: {
        tooltip: true
      },
      render(row: IndexObj) {
        return row.numDownload || 0
      }
    },
    {
      range: [
        navTypeList.FILE_TYPE,
        navTypeList.USER_RECYCLE,
        navTypeList.USER_SHARE_LINK
      ],
      title: '所在位置',
      key: 'pathInfo',
      minWidth: 150,
      width: 150,
      ellipsis: {
        tooltip: {
          raw: true,
          'content-style': {
            background: '#fef6d5',
            padding: '7px',
            fontSize: '13px'
          },
          'arrow-style': { border: 0, background: '#fff !important' }
        }
      },
      render(row: any) {
        return h(
          NButton,
          {
            class: 'text-[13px]',
            text: true,
            onClick(e: MouseEvent) {
              e.stopPropagation()
              // 跳转到目标位置
              const parent = row.pathInfo[row.pathInfo.length - 2]
              handleBreadClick(
                {
                  key: parent.id,
                  label: parent.filename,
                  myType: navTypeList.SOURCE
                },
                true,
                row.deleteFlag ? undefined : row
              )
            }
          },
          {
            default: () =>
              row.pathInfo
                .map((item: IndexObj) => {
                  return getLabelName(item.id, item.filename)
                })
                .join('/')
          }
        )
      }
    }
  ]

  return baseColumns.filter((item) => {
    if (!item.range) {
      return true
    } else {
      if (item.range.includes(explorerStore.curNav?.myType || 'source')) {
        return true
      }
      return false
    }
  })
})

const handlePageChange = (page?: number, pageSize?: number) => {
  page && (pageInfo.page = page)
  pageSize && (pageInfo.pageSize = pageSize)
  loadSources()
}

// 鼠标点击列表
const handleItemClick = (row: SourceRowData) => {
  !checkedRowKeys.value.some((item) => item.id === row.id)
    ? checkedRowKeys.value.push(row)
    : (checkedRowKeys.value = checkedRowKeys.value.filter(
        (item) => item.id !== row.id
      ))

  // loadSourceAuth(checkedRowKeys.value.map((item) => item.id))
}

// 侦听checkRow的变化，设置当前选中的文件详情
watch(
  () => checkedRowKeys.value.length,
  (newValue) => {
    if (newValue > 0) {
      loadSourceAuth(checkedRowKeys.value.map((item) => item.id))
      loadSourceRole(checkedRowKeys.value[checkedRowKeys.value.length - 1].id)
    } else {
      if (explorerStore.curNav!.myType === 'source') {
        loadSourceAuth([explorerStore.curNav!.key])
        loadSourceRole(explorerStore.curNav!.key)
      } else {
        //
        sourceAuths.value = []
      }
    }

    if (!newValue) {
      // 为当前导航信息
      const newLabel = getLabelName(
        explorerStore.curNav!.key,
        explorerStore.curNav!.label
      )
      explorerStore.curNav!.label = newLabel
      explorerStore.setCurSourceDesc({
        ...explorerStore.curNav
        // sourceRole: sourceRole.value
      })
    } else {
      const item = checkedRowKeys.value[checkedRowKeys.value.length - 1]
      explorerStore.setCurSourceDesc({
        ...item,
        key: item.id,
        label: item.filename,
        myType: navTypeList.SOURCE
        // sourceRole: sourceRole.value
      })
    }
  },
  {
    deep: true
  }
)

// const loadSource
watch(
  () => explorerStore.curNav,
  (newValue) => {
    if (newValue!.myType === 'source') {
      loadSourceAuth([newValue!.key])
      if (+newValue!.targetType === 2) {
        //
        loadSourceRole(newValue!.key)
      }
    }

    if (newValue && checkedRowKeys.value.length === 0) {
      // 为当前导航信息
      const newLabel = getLabelName(
        explorerStore.curNav!.key,
        explorerStore.curNav!.label
      )
      // console.log('nav change')
      console.log('curNav change', newValue, checkedRowKeys.value.length)
      explorerStore.curNav!.label = newLabel
      explorerStore.setCurSourceDesc({
        ...explorerStore.curNav,
        sourceRole: sourceRole.value
      })
    }
  },
  {
    deep: true
  }
)

const handleSelectChange = (keys: string[], rows: SourceRowData[]) => {
  checkedRowKeys.value = rows
  // loadSourceAuth(checkedRowKeys.value.map((item) => item.id))
}

// 加载文件列表
const loadSources = () => {
  loading.value = true

  return new Promise<void>((resolve, reject) => {
    // 根据当前nav的不同进行不同文件列表的查询
    const curType = explorerStore.curNav?.myType || navTypeList.SOURCE
    if (curType === navTypeList.SOURCE || curType === navTypeList.DEP) {
      getSourceByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        parentId: pageInfo.parentId,
        filename: pageInfo.filename,
        isDir: props.needDir ? 1 : undefined
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          // if(props.needDir){
          //   res.da
          // }
          data.value = res.data.items.map((item) => {
            return {
              ...item,
              isLeaf: !!item.isLeaf,
              isEdit: false,
              createType: 'rename'
            }
          })
          // console.log('before')
          data.value.sort((a, b) => b.isDir - a.isDir)
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else if (curType === navTypeList.FILE_TYPE) {
      if (props.needDir) {
        loading.value = false
        data.value = []
        resolve()
        return
      }
      getFileTypeSourceByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        fileType: explorerStore.curNav!.key,
        filename: pageInfo.filename
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          // curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          data.value = res.data.items.map((item) => {
            return {
              ...item,
              isLeaf: !!item.isLeaf,
              isEdit: false,
              createType: 'rename'
            }
          })
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else if (curType === navTypeList.USER_RECYCLE) {
      if (props.needDir) {
        loading.value = false
        data.value = []
        resolve()
        return
      }
      getBinSourceByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        filename: pageInfo.filename
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          // curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          data.value = res.data.items.map((item) => {
            return {
              ...item,
              isLeaf: !!item.isLeaf,
              isEdit: false,
              createType: 'rename'
            }
          })

          data.value.sort((a, b) => b.isDir - a.isDir)
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else if (curType === navTypeList.USER_SHARE_LINK) {
      // 外链分享
      getUserShareByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        type: 0,
        filename: pageInfo.filename
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          // curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          if (props.needDir) {
            res.data.items = res.data.items.filter((item) => {
              const item2 = item.source
              if (item2.isDir) {
                return true
              } else {
                return false
              }
            })
          }
          data.value = res.data.items.map((item) => {
            const item2 = item.source
            return {
              ...item2,
              numDownload: item.numDownload,
              numView: item.numView,
              isLeaf: !!item2.isLeaf,
              isEdit: false,
              createType: 'rename',
              shareId: item.id
            }
          })

          data.value.sort((a, b) => b.isDir - a.isDir)
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else if (curType === navTypeList.USER_SHARE) {
      // 内部协作分享
      getUserShareByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        type: 1,
        filename: pageInfo.filename
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          // curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          if (props.needDir) {
            res.data.items = res.data.items.filter((item) => {
              const item2 = item.source
              if (item2.isDir) {
                return true
              } else {
                return false
              }
            })
          }
          data.value = res.data.items.map((item) => {
            const item2 = item.source
            return {
              ...item2,
              isLeaf: !!item2.isLeaf,
              isEdit: false,
              createType: 'rename',
              shareId: item.id
            }
          })

          data.value.sort((a, b) => b.isDir - a.isDir)
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else if (curType === navTypeList.SHARE_TO_ME) {
      // 内部协作分享
      getUserInnerShareByPage({
        page: pageInfo.page,
        pageSize: pageInfo.pageSize,
        filename: pageInfo.filename
      })
        .then((res) => {
          pageResultInfo.total = res.data.total
          pageResultInfo.pages = res.data.pages
          // curFile.value = res.data.curSource
          // 按照文件夹在前，文件再后的顺序排序
          if (props.needDir) {
            res.data.items = res.data.items.filter((item) => {
              const item2 = item.source
              if (item2.isDir) {
                return true
              } else {
                return false
              }
            })
          }
          data.value = res.data.items.map((item) => {
            const item2 = item.source
            return {
              ...item2,
              isLeaf: !!item2.isLeaf,
              isEdit: false,
              createType: 'rename',
              shareId: item.id
            }
          })

          data.value.sort((a, b) => b.isDir - a.isDir)
        })
        .catch(console.error)
        .finally(() => {
          loading.value = false
          resolve()
        })
    } else {
      loading.value = false
      resolve()
    }
  })
}

// 表格中非叶子节点（文件夹下存在文件）加载
const handleLoad = (row: Record<string, unknown>) => {
  return new Promise<void>((resolve) => {
    // 加载文件夹下的子文件夹
    Promise.all([
      getSourceByPage({ page: 1, pageSize: 9999, parentId: row.id as string })
    ])
      .then(([res1]) => {
        const newSources = res1.data.items.map((item) => {
          return {
            ...item,
            isLeaf: !!item.isLeaf
          }
        })
        row.children = newSources
      })
      .finally(() => {
        resolve()
      })
  })
}

onMounted(async () => {
  if (!userStore.userInfo) {
    await userStore.getUserInfo()
  }

  // 初始化nav，如果nav没有值
  if (!explorerStore.curNav) {
    handleBreadClick({
      label: '个人空间',
      key: userStore.userInfo!.rootSourceId,
      myIcon: 'home',
      isLeaf: false,
      myType: navTypeList.SOURCE
    })
  } else {
    handleBreadClick(explorerStore.curNav, false)
  }
})

// ======================================== 子组件处理函数 ==========================================
const handleTreeMenuSelect = (key: string, menu: IndexObj[]) => {
  console.log(key, menu, 'menu')
  if (key === 'open') {
    handleToOpenSource(menu)
  } else if (key === 'download') {
    handleToDownloadSource(menu)
  } else if (key === 'shareTo') {
    handleToShareToSource()
  } else if (key === 'link') {
    handleToLinkSource()
  } else if (key === 'copy') {
    handleToCopySource(menu)
  } else if (key === 'cut') {
    handleToCutSource(menu)
  } else if (key === 'bin') {
    handleToBinSource(menu)
  } else if (key === 'createDump') {
    handleToCreateDumpSource()
  } else if (key === 'createZip') {
    handleToCreateZip()
  } else if (key === 'desc') {
    handleToViewSourceDesc()
  } else if (key === 'paste') {
    handleToPasteSource(menu)
  }
}

// ======================================== 选中文件的相关操作 ======================================

// 切换是否展示详情
const handleToChangeShowDesc = () => {
  explorerStore.setShowSourceDesc(
    '' + explorerStore.showDesc === '1' ? '0.75' : '1'
  )
}

const handleShowDesc = (value: number) => {
  explorerStore.setShowSourceDesc('' + value)
}

// 切换视图模式
const handleToChangeViewModel = (model: 'list' | 'grid') => {
  explorerStore.setSourceViewModel(model)
}

// 文件列表右键菜单
// 当前右键点击范围
const curRange = ref('')
const renderSourceDropDownMenu = (option: IndexObj) => {
  return renderDropLabel(option.myIcon, option.label, '#888', '15px', '#13b1fe')
}
const sourceDropDown = reactive<IndexObj>({
  showDropdown: false,
  x: 0,
  y: 0
})

const hoverSource = ref<SourceRowData>()
const sourcePopover = reactive<IndexObj>({
  showPopover: false,
  x: 0,
  y: 0
})

const renderUserInfo = (source: SourceRowData) => {
  if (!source.user) {
    return '已删除'
  } else {
    if (userStore.userInfo?.id === source.user.id) {
      return '我自己'
    }
    return source.user.username
  }
}

// 文件列表项hover事件
let timer: any = null
const userMouseoverProps = (row: SourceRowData, e: MouseEvent) => {
  e.preventDefault()
  e.stopPropagation()
  if (timer) {
    clearTimeout(timer)
    timer = null
  }
  timer = setTimeout(() => {
    hoverSource.value = row
    sourcePopover.showPopover = false
    nextTick().then(() => {
      sourcePopover.showPopover = true
      sourcePopover.x = e.clientX
      sourcePopover.y = e.clientY
    })
  }, 1500)
}

const userMouseleaveProps = (row: SourceRowData, e: MouseEvent) => {
  e.preventDefault()
  e.stopPropagation()
  sourcePopover.showPopover = false
  clearTimeout(timer)
  timer = null
}

// 加载文档权限

// 根据用户的权限和range来进行option的渲染
const sourceDropDownOptions = computed(() => {
  let baseMenu: IndexObj[] = []
  if (userStore.userInfo) {
    baseMenu = contextMenus.filter((item) => {
      let res = true
      if (item.auth) {
        if (item.auth.role && item.auth.role.length) {
          // 检查系统权限
          res =
            userStore.userInfo?.role.Permissions.some((v) => {
              return item.auth.role?.includes(v.ename)
            }) || false

          if (!res) {
            return res
          }
        }
        if (item.auth.doc && item.auth.doc.length) {
          // 检查文档权限
          res = sourceAuths.value.some((v) => {
            return item.auth.doc.includes(v)
          })

          if (!res) {
            return res
          }
        }

        if (item.auth.other) {
          // 检查其他
          if (item.auth.other.includes('len-1')) {
            // 需要checkrowkey为1
            res = checkedRowKeys.value.length === 1
            if (!res) {
              return res
            }
          }

          // 检查需要剪切板
          if (item.auth.other.includes('cut-exist')) {
            res = explorerStore.cutSourceList.length > 0
            if (!res) {
              return res
            }
          }

          // 检查更多的情况
          if (
            item.auth.other.includes('out-more') &&
            curRange.value === DropDownType.SOURCE_OUT
          ) {
            // 需要checkrowkey为1
            item!.children![0].disabled = !explorerStore.canforword
            item!.children![1].disabled = !explorerStore.canBack
          }
        }
      }
      if (item.range) {
        res = item.range.includes(curRange.value)
      }
      return res
    })
  } else {
    baseMenu = contextMenus.filter((item) => {
      if (item.auth) {
        return false
      } else {
        if (item.range) {
          return item.range.includes(curRange.value)
        } else {
          return true
        }
      }
    })
  }

  return baseMenu.filter((item) => {
    // 处理分割线
    if (item.type === 'divider' && item.needKey) {
      const keys = baseMenu
        .filter((item) => item.type !== 'divider')
        .map((v) => v.key)

      if (arraysIsEqual(keys, item.needKey)) {
        return false
      }
      return baseMenu.some((v) => item.needKey.includes(v.key))
    } else {
      return true
    }
  })
})

const handleSourceDropClickOutside = () => {
  sourceDropDown.showDropdown = false
}

// 文件右键菜单项被选择
const handleSourceDropSelect = (key: string) => {
  // console.log('key', key)

  // console.log(option, 'drop option')
  sourceDropDown.showDropdown = false
  if (key === 'open') {
    handleToOpenSource(checkedRowKeys.value[0])
  } else if (key === 'download') {
    handleToDownloadSource()
  } else if (key === 'shareTo') {
    handleToShareToSource()
  } else if (key === 'share-to-edit') {
    handleToShareToSource()
  } else if (key === 'share-to-close') {
    handleToCancelShare(1)
  } else if (key === 'link') {
    handleToLinkSource()
  } else if (key === 'share-link-edit') {
    handleToLinkSource()
  } else if (key === 'link-open') {
    // handleToLinkSource()
    handleToOpenLinkSource()
  } else if (key === 'share-link-close') {
    handleToCancelShare(0)
  } else if (key === 'copy') {
    handleToCopySource()
  } else if (key === 'cut') {
    handleToCutSource()
  } else if (key === 'rename') {
    handleToRenameSource()
  } else if (key === 'bin') {
    handleToBinSource()
  } else if (key === 'recycle') {
    handleToRecycleSource(0)
  } else if (key === 'all-recycle-bin') {
    handleToRecycleSource(1)
  } else if (key === 'del-complete') {
    handleToEmptyBin(0)
  } else if (key === 'empty-bin') {
    handleToEmptyBin(1)
  } else if (key === 'createDump') {
    handleToCreateDumpSource()
  } else if (key === 'createZip') {
    handleToCreateZip()
  } else if (key === 'desc') {
    handleToViewSourceDesc()
  } else if (key === 'reflesh') {
    const item = explorerStore.curNav
    handleBreadClick(
      {
        ...item,
        key: item!.id,
        label: item!.filename
      },
      false
    )
  } else if (key === 'upload') {
    handleToUploadFile()
  } else if (key === 'createDir') {
    handleToCreateDir()
  } else if (key.startsWith('new.')) {
    handleToCreateFile(key)
  } else if (key === 'paste') {
    handleToPasteSource()
  } else if (key === 'parent-folder-show') {
    handleToParentFolder()
  } else if (key === 'out-more-forward') {
    handleForward()
  } else if (key === 'out-more-back') {
    handleBack()
  } else if (key === 'out-view-list') {
    handleToChangeViewModel('list')
  } else if (key === 'out-view-grid') {
    handleToChangeViewModel('grid')
  }
}

// 文件列表项右键菜单事件注册
const userContextMenuProps = (row: SourceRowData) => {
  return (e: MouseEvent) => {
    if (!checkedRowKeys.value.some((item) => item.id === row.id)) {
      checkedRowKeys.value.push(row)
    }

    // 根据当前的路由nav计算出当前range
    curRange.value = navTypeToRange(explorerStore.curNav!.myType).range
    e.preventDefault()
    e.stopPropagation()
    sourceDropDown.showDropdown = false
    nextTick().then(() => {
      sourceDropDown.showDropdown = true
      sourceDropDown.x = e.clientX
      sourceDropDown.y = e.clientY
    })
  }
}

// 外层的右键菜单
// 文件表格外空白区域被点击
const hanldeOutContextMenu = (e: MouseEvent) => {
  curRange.value = navTypeToRange(explorerStore.curNav!.myType).outRange
  e.preventDefault()
  e.stopPropagation()
  sourceDropDown.showDropdown = false
  nextTick().then(() => {
    sourceDropDown.showDropdown = true
    sourceDropDown.x = e.clientX
    sourceDropDown.y = e.clientY
  })
}

const afterOpt = () => {
  checkedRowKeys.value = []
  loadSources()
}

// 打开文件
const handleToOpenSource = (item: IndexObj) => {
  if (item.deleteFlag) {
    return
  }
  // 根据文件类型的不同，进行处理
  if (item.isDir) {
    handleBreadClick({
      ...item,
      key: item.id,
      label: item.filename,
      myType: navTypeList.SOURCE
    })
  } else {
    // 文件预览的逻辑
  }
}

//下载文件
const handleToDownloadSource = (sources?: IndexObj[]) => {
  // 根据选中文件的情况按需下载，如果都是文件类型，多次调用单文件接口
  // 如果存在文件夹类型，调用打包下载接口
  const finalSources = sources || checkedRowKeys.value
  const isNeedPack = finalSources.some((item) => {
    return item.isDir === 1
  })

  handleDownloadSource(isNeedPack, finalSources)
}

const handleDownloadSource = async (
  isNeedPack: boolean,
  finalSources: IndexObj[]
) => {
  if (isNeedPack) {
    // 打包下载
    const res = await zipDownload({
      sourceIds: finalSources.map((item) => item.id)
    })

    // 命名，如果为一个文件夹，则命名为该文件夹的名称,
    // 如果为多个文件夹和文件，则命名为父级文件的名称，也就是curNav的名称
    const zipName =
      finalSources.length === 1
        ? finalSources[0].filename
        : explorerStore.curNav?.label

    downLoadFile(res, `${zipName}.zip`)
  } else {
    // 单文件下载
    for (let i = 0; i < finalSources.length; i++) {
      const res = await fileDownload({
        sourceId: finalSources[i].id
      })
      downLoadFile(res, finalSources[i].filename)
    }
  }
}

// 内部协作
const handleToShareToSource = (source?: SourceRowData) => {
  const finalSource = source || checkedRowKeys.value[0]
  if (!finalSource) {
    message.warning('请选择文件')
  }
  // 根据当前资源的情况进行处理
  shareSource.value = finalSource
  dialogs.shareTo = true
}

const shareSource = ref<any>()
// 外链分享
const handleToLinkSource = (source?: SourceRowData) => {
  const finalSource = source || checkedRowKeys.value[0]
  if (!finalSource) {
    message.warning('请选择文件')
  }
  // 根据当前资源的情况进行处理
  shareSource.value = finalSource

  dialogs.linkShare = true
}

// 打开外链分享页面
const handleToOpenLinkSource = (source?: SourceRowData) => {
  const finalSource = source || checkedRowKeys.value[0]
  if (!finalSource) {
    message.warning('请选择文件')
  }
  // 根据当前资源的情况进行处理
  shareSource.value = finalSource

  // console.log(finalSource)

  router.push({
    name: 'linkShare',
    query: {
      shareId: finalSource.Share.id
    }
  })
}

const handleLinkShareFinish = () => {
  dialogs.linkShare = false
  afterOpt()
}

const handleShareToFinish = () => {
  dialogs.shareTo = false
  afterOpt()
}

// 取消分享
const handleToCancelShare = (type: number, sources?: SourceRowData[]) => {
  const finalSource = sources || checkedRowKeys.value
  if (!finalSource) {
    message.warning('请选择文件')
  }
  dialog.warning({
    title: '提示',
    content: '你确定要取消该分享吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      load.show()
      cancelShare({
        shareIds: finalSource.map((item) => item.shareId),
        type
      })
        .then(() => {
          message.success('操作成功')
          afterOpt()
        })
        .catch(console.error)
        .finally(() => {
          load.hide()
        })
    },
    onNegativeClick: () => {}
  })
}

// 拖拽移动
const handleDrop = (row: any, e: DragEvent) => {
  e.stopPropagation()
  e.preventDefault()
  // item.isHover = false
  // console.log(item, props.checkedRowKeys)
  const finalSources = checkedRowKeys.value
  if (!finalSources.length) {
    return message.warning('请选择文件')
  }
  // 回收站不支持此类操作
  if (explorerStore.curNav!.myType === navTypeList.USER_RECYCLE) {
    return message.warning('回收站不支持剪切操作')
  }
  load.show()
  moveSource({
    parentId: row.id,
    sourceIds: checkedRowKeys.value.map((item) => item.id)
  })
    .then(() => {
      message.success('文件移动成功')
      afterOpt()
    })
    .catch(console.error)
    .finally(() => {
      load.hide()
    })
}

const handleDragOver = (row: any, e: DragEvent) => {
  if (row.isDir && !checkedRowKeys.value.some((v) => v.id === row.id)) {
    e.preventDefault()
  }
}

// 复制文件
const handleToCopySource = (sources?: IndexObj[]) => {
  const finalSources = sources || checkedRowKeys.value

  // 将选中文件存入store
  if (!finalSources.length) {
    return message.warning('请选择文件')
  }

  // 回收站不支持此类操作
  if (explorerStore.curNav!.myType === navTypeList.USER_RECYCLE) {
    return message.warning('回收站不支持复制操作')
  }

  explorerStore.setCopySourceList(finalSources.map((item) => ({ ...item })))
  message.success('复制-[覆盖剪切板成功]')
}

// 剪切文件
const handleToCutSource = (sources?: IndexObj[]) => {
  const finalSources = sources || checkedRowKeys.value
  if (!finalSources.length) {
    return message.warning('请选择文件')
  }
  // 回收站不支持此类操作
  if (explorerStore.curNav!.myType === navTypeList.USER_RECYCLE) {
    return message.warning('回收站不支持剪切操作')
  }
  explorerStore.setCutSourceList(finalSources.map((item) => ({ ...item })))
  message.success('剪切-[覆盖剪切板成功]')
}

const handleToRenameSource = () => {
  checkedRowKeys.value[0].isEdit = true
}
// 重命名文件
const handleRenameSource = (row: IndexObj) => {
  load.show()
  renameSource({
    sourceId: row.id,
    filename: row.filename
  })
    .then(() => {
      message.success('重命名文件成功')
    })
    .catch(() => {
      row.isEdit = true
    })
    .finally(() => {
      load.hide()
    })
}

// 文件放入回收站
const handleToBinSource = (sources?: IndexObj[]) => {
  const finalSources = sources || checkedRowKeys.value
  handleBinSource(finalSources.map((item) => item.id))
}

const handleBinSource = (sourceIds: string[]) => {
  dialog.warning({
    title: '提示',
    content: '你确定要删除这些文件吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      load.show()
      binSource({ sourceIds })
        .then(() => {
          message.success('删除成功-移入回收站成功')
          afterOpt()
        })
        .catch(console.error)
        .finally(() => {
          load.hide()
        })
    },
    onNegativeClick: () => {}
  })
}

// 文件还原
const handleToRecycleSource = (isAll: number) => {
  //还原选中部分的文件
  load.show()
  recSource({
    binSourceIds: checkedRowKeys.value.map((item) => item.binSourceId),
    isAll
  })
    .then(() => {
      message.success('还原成功')
      afterOpt()
    })
    .catch(console.error)
    .finally(() => {
      load.hide()
    })
}

// 清空回收站
const handleToEmptyBin = (isAll: number) => {
  dialog.warning({
    title: '提示',
    content: '你确定要彻底删除这些文件吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: () => {
      load.show()
      delSource({
        binSourceIds: checkedRowKeys.value.map((item) => item.binSourceId),
        isAll
      })
        .then(() => {
          message.success('彻底删除成功')
          afterOpt()
        })
        .catch(console.error)
        .finally(() => {
          load.hide()
        })
    },
    onNegativeClick: () => {}
  })
}

// 创建文件副本
const handleToCreateDumpSource = () => {}

// 创建压缩包
const handleToCreateZip = () => {}

//查询文件属性
const handleToViewSourceDesc = () => {
  // 展示dialog以及sourceDesc面板
  dialogs.sourceDesc = true
}

// 创建文件夹
const handleToCreateDir = () => {
  // 自动获取新建文件夹的数量，以下标递增的方式命名
  data.value[0] && (data.value[0].isEdit = false)
  const filename = formatFilenameByInc(data.value, '新建文件夹')
  const obj: any = {
    id: filename,
    filename,
    parentId: explorerStore.curNav!.key,
    targetType: 1,
    targetId: '',
    parentLevel: '',
    isDir: 1,
    type: 0,
    deleteFlag: 0,
    createTime: Date.now(),
    updateTime: Date.now(),
    createUser: userStore.userInfo?.id,
    updateUser: userStore.userInfo?.id,
    viewTime: '',
    user: {
      id: userStore.userInfo?.id,
      username: '',
      avator: userStore.userInfo?.avator
    },
    hasFile: 0,
    hasFolder: 0,
    isLeaf: true,
    isEdit: true,
    createType: 'createDir'
  }
  data.value.unshift(obj)
}

const handleCreateDir = (row: IndexObj) => {
  load.show()
  createSourceDir({
    dirName: row.filename,
    parentId: row.parentId
  })
    .then(() => {
      message.success('新建文件夹成功')
      afterOpt()
    })
    .catch(console.error)
    .finally(() => {
      load.hide()
    })
}

// 创建文件
const handleToCreateFile = (fileType: string) => {
  // 自动获取新建文件夹的数量，以下标递增的方式命名
  data.value[0] && (data.value[0].isEdit = false)
  const filename = formatFilenameByInc(
    data.value,
    '新建文件.' + fileType.slice(((fileType.lastIndexOf('.') - 1) >>> 0) + 2)
  )
  // 根据后缀名获取类型
  const fileTypeInfo = getFileTypeBySuffix(filename as string)

  const obj: any = {
    id: filename,
    filename,
    parentId: explorerStore.curNav!.key,
    targetType: 1,
    targetId: '',
    parentLevel: '',
    isDir: 0,
    type: fileTypeInfo.type,
    deleteFlag: 0,
    createTime: Date.now(),
    updateTime: Date.now(),
    createUser: userStore.userInfo?.id,
    updateUser: userStore.userInfo?.id,
    viewTime: '',
    user: {
      id: userStore.userInfo?.id,
      username: '',
      avator: userStore.userInfo?.avator
    },
    hasFile: 0,
    hasFolder: 0,
    isLeaf: true,
    isEdit: true,
    createType: 'createFile'
  }
  data.value.unshift(obj)
}

const handleCreateFile = (row: IndexObj) => {
  load.show()
  createFile({
    filename: row.filename,
    parentId: row.parentId,
    type: row.type
  })
    .then(() => {
      message.success('新建文件成功')
      afterOpt()
    })
    .catch(console.error)
    .finally(() => {
      load.hide()
    })
}

const dialogs = reactive({
  upload: false,
  sourceDesc: false,
  linkShare: false,
  shareTo: false,
  docAuth: false
})

// 去上传文件
const fileDragover = (e: DragEvent) => {
  // console.log(e)
  e.preventDefault()
}

const fileDrop = (e: DragEvent) => {
  e.preventDefault()
  if (explorerStore.curNav!.myType !== navTypeList.SOURCE) {
    message.warning('不支持上传操作')
    return
  }

  if (!e.dataTransfer) {
    return
  }
  const files = e.dataTransfer.files // 获取到所有的文件对象
  handleToUploadFile()
  setTimeout(() => {
    events.emit('upload-file', {
      files
    })
  }, 100)
}
const handleToUploadFile = () => {
  dialogs.upload = true
}

const handleUploadFinish = () => {
  dialogs.upload = false
  afterOpt()
}

// 去粘贴文件
const handleToPasteSource = (sources?: IndexObj[]) => {
  let parentId = explorerStore.curNav!.key
  if (!sources) {
    if (explorerStore.curNav!.myType !== navTypeList.SOURCE) {
      message.warning('不支持粘贴操作')
      return
    }
  } else {
    parentId = sources[0].id
  }
  // 复制或者移动文件，根据store里面的类型确定
  if (explorerStore.cutModel === 'cut') {
    // 进行剪切
    load.show()
    moveSource({
      parentId,
      sourceIds: explorerStore.cutSourceList.map((item) => item.id)
    })
      .then(() => {
        message.success('移动文件成功')
        afterOpt()
        explorerStore.setCutSourceList([])
      })
      .catch(console.error)
      .finally(() => {
        load.hide()
      })
  } else {
    load.show()
    copySource({
      parentId,
      sourceIds: explorerStore.cutSourceList.map((item) => item.id)
    })
      .then(() => {
        message.success('复制文件成功')
        afterOpt()
        explorerStore.setCopySourceList([])
      })
      .catch(console.error)
      .finally(() => {
        load.hide()
      })
  }
}

// 上层文件夹显示
const handleToParentFolder = () => {
  const row = checkedRowKeys.value[0]
  // 跳转到目标位置
  const parent = row.pathInfo[row.pathInfo.length - 2]
  handleBreadClick(
    {
      key: parent.id,
      label: parent.filename,
      myType: navTypeList.SOURCE
    },
    true,
    row.deleteFlag ? undefined : (row as any)
  )
}

// 监听键盘事件，cv
const handleKeyUp = function (e: KeyboardEvent) {
  if (e.ctrlKey && e.key === 'c') {
    handleToCopySource()
  } else if (e.ctrlKey && e.key === 'x') {
    handleToCutSource()
  } else if (e.ctrlKey && e.key === 'v') {
    handleToPasteSource()
  } else if (e.ctrlKey && e.key === 'a') {
    if ((e.target as any).nodeName === 'INPUT') {
      return
    }
    e.preventDefault()
    e.stopPropagation()
    checkedRowKeys.value = data.value
  }
  if (e.ctrlKey && e.key === 'd') {
    // e.preventDefault()
    e.preventDefault()
    // e.stopPropagation()
    handleToBinSource()
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleKeyUp)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleKeyUp)
})
</script>

<style scoped lang="scss">
.explorer-container {
  font-size: 13px;
  :deep(.n-data-table-tbody .n-data-table-tr:hover .n-data-table-td) {
    background-color: #e5f3ff;
    .move {
      opacity: 0.85;
    }
  }

  :deep(.n-data-table-tbody .n-data-table-tr.selected .n-data-table-td) {
    background-color: #e5f3ff;
    // border: 1px solid #93cfff;
    border-left: none;
    border-right: none;
    border-bottom: 1px solid #93cfff;
    .move {
      opacity: 0.85;
    }
  }

  :deep(.n-data-table-tbody) {
    // border-left: 1px solid #93cfff;
    user-select: none;
  }

  :deep(
      .n-data-table-tbody
        .n-data-table-tr.selected
        .n-data-table-td:first-of-type
    ) {
    // border-left: 1px solid #93cfff;
  }

  :deep(
      .n-data-table-tbody
        .n-data-table-tr.selected
        .n-data-table-td:last-of-type
    ) {
    // border-right: 1px solid #93cfff;
  }

  // :deep(.n-data-table-tbody .n-data-table-tr) {
  //   &:nth-child(n + 2 of .selected) .n-data-table-td {
  //     // border-top: 1px solid #93cfff;
  //     border-top: 0;
  //   }
  // }

  :deep(.n-data-table-tbody td[data-col-key='name']) {
    display: flex;
    align-items: center;
  }

  .btn-active {
    background-color: #e4f8ff;
    border-color: #93cfff;
  }

  .file-info-container {
    .header {
      min-width: 400px;
      position: relative;
      background: #fff url('@/assets/images/bg.gif') 0 10px repeat-x;
      overflow: auto;

      .header-nav {
        // overflow: auto;
        position: relative;
        // display: flex;
        padding-top: 12px;
        padding-left: 10px;
        height: 37px;
        // align-items: center;
        .g-scroll {
          // top: 12px;
          left: 56px;
          position: absolute;
          width: 28px;
          height: 400px;
          overflow: scroll;
          overflow-x: hidden;
          border: 1px solid rgb(224, 224, 230);
          border-bottom: none;
          box-sizing: border-box;
          transform-origin: 100% 0;
          transform: rotate(-90deg);

          &::-webkit-scrollbar {
            width: 1px;
            height: 1px;
          }
          &::-webkit-scrollbar-button {
            width: 1px;
            height: 1px;
          }
        }
        .g-pesudo {
          width: 28px;
          // height: 2000px;
          background: linear-gradient(
            rgba(122, 122, 50, 0.3),
            rgba(20, 200, 150, 0.3)
          );
        }

        .g-content {
          position: absolute;
          top: 0;
          left: 28px;
          // width: 2000px;
          height: 28px;
          // border: 1px solid #888;
          transform-origin: 0 0;
          transform: rotate(90deg);
        }
      }

      .file-actions {
        overflow: auto;
        width: 100%;
        padding-left: 10px;
        height: 37px;
        min-width: 505px;
        // overflow: hidden;
        border-bottom: 1px solid #e6e6e6;
        background: #fefefe;
        -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.02);
        -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.02);
        box-shadow: 0 5px 10px rgba(0, 0, 0, 0.02);
      }
    }

    .myTable {
      width: 100%;
      // min-width: 500px;
      overflow: auto;
      height: calc(100vh - 74px);
    }
  }
}
</style>
